%skeleton "lalr1.cc"
%require "3.0.4"
%define api.namespace {Marker}
%define parser_class_name {Parser}
%define api.token.constructor
%define api.value.type variant
%define api.token.prefix {TOKEN_}
%define parse.assert
%defines
%code requires
{
    #include <iostream>
    #include <string>
    #include <vector>
    #include <stdint.h>
    #include <cmath>
    using namespace std;

    namespace Marker {
        class Scanner;
        class Driver;
    }
}

%code top
{
    #include <iostream>
    #include "scanner.h"
    #include "parser.hpp"
    #include "driver.h"
    #include "location.hh"
    #include "log.h"

    static Marker::Parser::symbol_type yylex(Marker::Scanner& scanner,Marker::Driver &driver)
    {
        return scanner.nextToken();
    }
    using namespace Marker;
}

%lex-param { Marker::Scanner& scanner }
%lex-param { Marker::Driver& driver }
%parse-param { Marker::Scanner& scanner }
%parse-param { Marker::Driver& driver }

%locations
// %define parse-trace
%define parse.error verbose

%token END 0

/* import from lexer.l */
%token<string> SELECTOR
%token<string> ATTRIBUTE
%token<string> VALUE
%token CHAR_L_BRACE              /* ( */
%token CHAR_R_BRACE              /* ) */
%token CHAR_COLON                /* : */
%token CHAR_SEMICOLON            /* ; */

/* non-terminate-symbol */
%start statements
%type<string> css_block css_block_begin css_block_end
%type<string> declare

%%

statements: css_block statements
{
    mylog::debug("statements: css_block statements");
}

statements: declare statements
{
    mylog::debug("statements: declare statements (%s)", $1.c_str());
}

statements: %empty
{
    mylog::debug("statements: ");
}

css_block: css_block_begin css_block_end
{
    mylog::debug("css_block: css_block_begin css_block_end");
}

css_block_begin: SELECTOR CHAR_L_BRACE
{
    mylog::info("css_block_begin: SELECTOR CHAR_L_BRACE (%s)", $1.c_str());
    driver.current->blocks[$1].parent = driver.current;
    driver.current = &driver.current->blocks[$1];
}

css_block_end: statements CHAR_R_BRACE
{
    mylog::info("css_block_end: statements CHAR_R_BRACE");
    driver.current = driver.current->parent;
}

declare: ATTRIBUTE CHAR_COLON VALUE CHAR_SEMICOLON
{
    mylog::info("declare: ATTR CHAR_COLON VALUE CHAR_SEMICOLON (%s: %s;)", $1.c_str(), $3.c_str());
    $$ = $1 + ": " + $3 + ";";
    driver.current->declares[$1] = $3;
}

%%

void Marker::Parser::error(const Marker::location& location,const std::string& message)
{
    mylog::warn("error: (%d,%d) - (%d,%d): %s",
          location.begin.line, location.begin.column,
          location.end.line, location.end.column,
          message.c_str());
}
